using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Net;

namespace FileUploader
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }
        private string _clinetID="";
        private CookieContainer _sessionContainer = new CookieContainer();

        private void frmMain_Load(object sender, EventArgs e)
        {
            //SystemInfo systemInfo = new SystemInfo();
            //_clinetID = systemInfo.GetMainHardDiskId();
            //this.status_idInfo.Text = string.Format("Welcome: {0}, your Id is {1}", System.Environment.MachineName, _clinetID);

            //load servers
            string[] servers = System.Configuration.ConfigurationManager.AppSettings.AllKeys;
            for (int i = 0; i < servers.Length; i++)
            {
                ListViewItem item = new ListViewItem(servers[i]);
                item.ImageIndex = 0;
                this.lv_server.Items.Add(item);
            }
            
    
         
            //test();
        }

        private void test()
        {
            this.lv_uploadStatus.Columns.Add("Name", 60, HorizontalAlignment.Right);
            lv_uploadStatus.Columns.Add("FileSize", 100, HorizontalAlignment.Left);
            lv_uploadStatus.Columns.Add("Percentage", 100, HorizontalAlignment.Left);
            lv_uploadStatus.Columns.Add("TotalSeconds", 100, HorizontalAlignment.Left);
            lv_uploadStatus.Columns.Add("LocalFile", 100, HorizontalAlignment.Left);
            lv_uploadStatus.Columns.Add("RemoteFile", 100, HorizontalAlignment.Left);
            for (int i = 0; i < 5; i++)
            {
                ListViewItem li = new ListViewItem();

                li.SubItems.Clear();
                li.SubItems[0].Text = "tt";
                li.SubItems.Add(i.ToString());
                li.SubItems.Add(i.ToString());
                li.SubItems.Add(i.ToString());
                li.SubItems.Add(i.ToString());
                li.SubItems.Add(i.ToString());
                
                this.lv_uploadStatus.Items.Add(li);
            }
        }

        #region Explore module: folders and files
        private string _currentServerIpAddress;
        private void lv_server_DoubleClick(object sender, EventArgs e)
        {
            //change server
            if (this.lv_server.FocusedItem == null)
                return;

            string name = this.lv_server.FocusedItem.Text;
             
            _currentServerIpAddress = System.Configuration.ConfigurationManager.AppSettings[name];

            _remoteFileExplorer.Url = _currentServerIpAddress + "/Explorer.asmx";
            _remoteFileExplorer.CookieContainer = _sessionContainer;

            frmLogin login = new frmLogin();
            login.ShowDialog();
            _remoteFileExplorer.Login(login.UserName, login.Password);

            _currentServerRootDir = _remoteFileExplorer.GetRootPath();
            ShowDir(_currentServerRootDir);
            ShowFiles(_currentServerRootDir);

            ArrayList pendingTask = Task.LoadTasks(_remoteFileExplorer);
            for (int i = 0; i < pendingTask.Count; i++)
            {
                Uploader uploader = new Uploader(pendingTask[i] as Task);
                uploader.Strat();
                _taskList.Add(uploader);

            }
            if (pendingTask.Count > 0)
            {
                Timer timer = new Timer();
                timer.Tick += new EventHandler(timer_showStatus_Tick);
                timer.Interval = 2 * 1000; //every 2 seconds
                timer.Enabled = true;
                timer.Start();
            }
        }
        

        private FileExplorer.Explorer _remoteFileExplorer = new FileUploader.FileExplorer.Explorer();
        private string _currentServerRootDir;

        private string _currentServerActiveDir;
        private void ShowDir(string path)
        {
            lv_folders.Items.Clear();

            _currentServerActiveDir = path;
            if (_currentServerRootDir != path)
            {
                string parent = Path.GetFileName(path);
                ListViewItem itemP = new ListViewItem("..");
                itemP.Tag = Directory.GetParent(path);
                itemP.ImageIndex = 1;
                lv_folders.Items.Add(itemP);
            }
           
            string[] dirs = _remoteFileExplorer.GetChildDirs(path);
            for (int i = 0; i < dirs.Length; i++)
            {
                string dirName = Path.GetFileName(dirs[i]);
                ListViewItem item = new ListViewItem(dirName);
                item.Tag = dirs[i];
                item.ImageIndex = 2;
                lv_folders.Items.Add(item);
            }
        }
        private void ShowFiles(string path)
        {
            this.lv_files.Items.Clear();

            
            string[] files = _remoteFileExplorer.GetChildFiles(path);//
            for (int i = 0; i < files.Length; i++)
            {
                string fName = Path.GetFileName(files[i]);
                ListViewItem item = new ListViewItem(fName);
                item.Tag = files[i];
                item.ImageIndex = 3;
                lv_files.Items.Add(item);
            }
        }
        private void lv_folders_DoubleClick(object sender, EventArgs e)
        {
            if (lv_folders.FocusedItem != null && lv_folders.FocusedItem.Tag != null)
            {
                string folder = lv_folders.FocusedItem.Tag.ToString();
                ShowDir(folder);
                ShowFiles(folder);
            }
        }

        //donwload some small things to check
        private void lv_files_DoubleClick(object sender, EventArgs e)
        {
            if (lv_files.FocusedItem != null)
            {
                string file = _currentServerActiveDir + "\\" + lv_files.FocusedItem.Text;
              
                byte[] content = _remoteFileExplorer.GetFile(file);
                if (content.Length == 0)
                    MessageBox.Show("File is too big to download");
                else
                {
                    string local = Path.GetTempPath() + lv_files.FocusedItem.Text;
                    if(File.Exists(local))
                        File.Delete(local);
                    File.WriteAllBytes(local, content);
                    Process.Start(local);
                }
            }
        }

        private void lv_files_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Link;
        }
        private void lv_files_DragDrop(object sender, DragEventArgs e)
        {
            //string[] files=  e.Data.GetData("FileNameW");
            string[] fileNames = (string[])e.Data.GetData(DataFormats.FileDrop);
            for (int i = 0; i < fileNames.Length; i++)
            {
                for (int k = 0; k < this.lv_files.Items.Count; k++)
                {
                    if (Path.GetFileName(fileNames[i]) == Path.GetFileName(this.lv_files.Items[k].Text))
                    {
                        DialogResult dr=   MessageBox.Show("There is a file '" + Path.GetFileName(fileNames[i]) + "' already exsit,Click 'Yes' to Backup and Replace it, Click 'No' to Replace the file, or Click 'Cancel' to cancel", "Upload options", MessageBoxButtons.YesNoCancel);
                        string remoteFile = _currentServerActiveDir + "\\" + Path.GetFileName(fileNames[i]);
                        if (dr == DialogResult.Cancel)
                        {
                            return;
                        }
                        if (dr == DialogResult.Yes)
                        { 
                           //copy and replace
                            MessageBox.Show(_remoteFileExplorer.BackupAndDelete(remoteFile));
                        }
                        if (dr == DialogResult.No)
                        {
                            MessageBox.Show(_remoteFileExplorer.DeleteFile(remoteFile));
                        }
                    }
                }
            }

            //if first time to upload in this session
            if (this.lv_uploadStatus.Items.Count == 0)
            {
                //timmer to show the status
                Timer timer = new Timer();
                timer.Tick += new EventHandler(timer_showStatus_Tick);
                timer.Interval = 2 * 1000; //every 2 seconds
                timer.Enabled = true;
                timer.Start();
            }
            AddTask(fileNames);
        }
        //copy out
        private void lv_files_DragOver(object sender, DragEventArgs e)
        {
            //e.AllowedEffect = DragDropEffects.Link;
        }
        private void lv_files_DragLeave(object sender, EventArgs e)
        {
            //this.Text = DateTime.Now.ToLongTimeString();
        }
        /// <summary>
        /// drag to download
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lv_files_ItemDrag(object sender, ItemDragEventArgs e)
        {
            string file = _currentServerActiveDir + "\\" + lv_files.FocusedItem.Text;

            byte[] content = _remoteFileExplorer.GetFile(file);
            if (content.Length == 0)
                MessageBox.Show("File is too big to download");
            else
            {
                //how to get current document path? 
                string local = Path.GetTempPath() + lv_files.FocusedItem.Text;
                if (File.Exists(local))
                    File.Delete(local);

                File.WriteAllBytes(local, content);
                //using (StreamWriter writer = new StreamWriter(local))
                //{
                //    writer.BaseStream.Write(content, 0, content.Length);
                //}

                DataObject data = new DataObject("FileDrop", new string[] { local });
                DoDragDrop(data, DragDropEffects.Move);

            }

    
        }
        #endregion

        #region Explorer module: operation
        private void RefreshFolderAndFile()
        {
            //refresh files
            ShowDir(_currentServerActiveDir);
            ShowFiles(_currentServerActiveDir);
        }
        private void TestPermission()
        {
            string res = this._remoteFileExplorer.TestPermission(_currentServerActiveDir);
            MessageBox.Show(res);
        }
        private void CreateFolder()
        {
            frmCreateFolder cf = new frmCreateFolder();
            cf.ShowDialog();
            string name = cf.FolderName;
            if (name != "")
            {
                name = this._currentServerActiveDir + "\\" + name;
                MessageBox.Show(_remoteFileExplorer.CreateFolder(name));
            }
        }
        private void DeleteFolder()
        {
            if (lv_folders.FocusedItem != null && lv_folders.FocusedItem.Tag != null)
            {
                string folder = lv_folders.FocusedItem.Tag.ToString();
                if (DialogResult.Yes == MessageBox.Show("are you sure to remove this folder '" + folder + "'?", "Remove Folder", MessageBoxButtons.YesNoCancel))
                {
                    MessageBox.Show(_remoteFileExplorer.RemoveFolder(folder));
                }
            }
        }
        private void DeleteFile()
        {
            if (lv_files.FocusedItem != null)
            {
                string file = _currentServerActiveDir + "\\" + lv_files.FocusedItem.Text;
                if (DialogResult.Yes == MessageBox.Show("are you sure to remove this file '" + file + "'?", "Remove File", MessageBoxButtons.YesNoCancel))
                {
                    MessageBox.Show(_remoteFileExplorer.BackupAndDelete(file));
                }
            }
        } 
        #endregion

        #region upload
        void timer_showStatus_Tick(object sender, EventArgs e)
        {
            //update the status of UI
            int seconds = (sender as Timer).Interval / 1000;
            //this.dataGridView1.DataSource = GetUpdatedStatusAsDT(_taskList, seconds);
            BindProgress2List(GetUpdatedStatusAsDT(_taskList, seconds));
        }
        ArrayList _taskList = new ArrayList();
        private int _fileChunkCount = 2;
        private void AddTask(string[] files)
        {
            //_taskList = new ArrayList();
            for (int i = 0; i < files.Length; i++)
            {
                Task tast = new Task();

                tast.DataReceiver = this._remoteFileExplorer;
                tast.FileChunkCount = Convert.ToInt32(_fileChunkCount);
                tast.LocalFile = files[i];
                tast.RemoteFile = _currentServerActiveDir + "\\" + Path.GetFileName(tast.LocalFile);//rename path????
                tast.Name = Path.GetFileName(tast.LocalFile);
                //t.Percentage=0;
                tast.TotalSeconds = 0;

                tast.Init(); //init, split the file to upload

                //_taskList.Add(t);

                Uploader uploader = new Uploader(tast);
                uploader.Strat();
                _taskList.Add(uploader);
            }

            //show in UI
            //this.lv_uploadStatus = GetUpdatedStatusAsDT(_taskList, 0);
            //BindProgress2List(GetUpdatedStatusAsDT(_taskList, 0));
        }
        private void BindProgress2List(DataTable dt)
        {
            this.lv_uploadStatus.Items.Clear();
            if (this.lv_uploadStatus.Columns.Count < 5)
            {
                lv_uploadStatus.Columns.Add("Name", 80, HorizontalAlignment.Right);
                lv_uploadStatus.Columns.Add("FileSize", 80, HorizontalAlignment.Left);
                lv_uploadStatus.Columns.Add("Percentage", 80, HorizontalAlignment.Left);
                lv_uploadStatus.Columns.Add("TotalSeconds", 80, HorizontalAlignment.Left);
                lv_uploadStatus.Columns.Add("LocalFile", 100, HorizontalAlignment.Left);
                lv_uploadStatus.Columns.Add("RemoteFile", 100, HorizontalAlignment.Left);
            }
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                ListViewItem li = new ListViewItem();

                li.SubItems.Clear();
                li.SubItems[0].Text = dt.Rows[i]["Name"].ToString();
                li.SubItems.Add(dt.Rows[i]["FileSize"].ToString());
                li.SubItems.Add(dt.Rows[i]["Percentage"].ToString());
                li.SubItems.Add(dt.Rows[i]["TotalSeconds"].ToString());
                li.SubItems.Add(dt.Rows[i]["LocalFile"].ToString());
                li.SubItems.Add(dt.Rows[i]["RemoteFile"].ToString());

                this.lv_uploadStatus.Items.Add(li);
            }
        }
        /// <summary>
        /// get result as datatable. and save status to db
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private DataTable GetUpdatedStatusAsDT(ArrayList list, int intvScds)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Name");
            dt.Columns.Add("FileSize");
            dt.Columns.Add("Percentage");
            dt.Columns.Add("TotalSeconds");
            dt.Columns.Add("LocalFile");
            dt.Columns.Add("RemoteFile");

            for (int i = 0; i < list.Count; i++)
            {
                //update task status to db

                Task tast = (list[i] as Uploader).Task;
                if (tast.Percentage < 100)
                {
                    tast.TotalSeconds += intvScds;//running time
                    tast.Save();//save the status to db, so next time can load the status to continue.
                }
                else //100 percent, stop save and clear thread to stop
                {
                    for (int j = 0; j < tast.FileChunks.Count; j++)
                    {
                        FileChunk fc = tast.FileChunks[j] as FileChunk;
                        fc.Stop();
                    }
                }
                DataRow dr = dt.NewRow();
                dr["Name"] = tast.Name;
                dr["FileSize"] = tast.FileSize;
                dr["Percentage"] = tast.Percentage;
                dr["TotalSeconds"] = tast.TotalSeconds;
                dr["LocalFile"] = tast.LocalFile;
                dr["RemoteFile"] = tast.RemoteFile;

                dt.Rows.Add(dr);
            }
            return dt;
        }
        //
 
        private void ClearTask()
        {
            for (int i = 0; i < _taskList.Count; i++)
            {
                (_taskList[i] as Uploader).Task.Remove();
            }
            _taskList.Clear();
        }
        // 
        #endregion

        #region menu and buttons
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            RefreshFolderAndFile();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            //remove tasks
            ClearTask();
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            //test permision
            TestPermission();
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            //create folder
            CreateFolder();
        }

        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            //delete folder
            DeleteFolder();
        }

        private void toolStripButton6_Click(object sender, EventArgs e)
        {
            //delete file
            DeleteFile();
        }

        private void reToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RefreshFolderAndFile();
        }

        private void testPermissionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TestPermission();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void createFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //create folder
            CreateFolder();
        }

        private void deleteFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {  //delete folder
            DeleteFolder();

        }

        private void deleteFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //delete file
            DeleteFile();
        }
        private void toolStripButton7_Click(object sender, EventArgs e)
        {
            //conn 2 server
            lv_server_DoubleClick(null, null);
        }

        private void connectToServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //conn 2 server
            lv_server_DoubleClick(null, null);
        }

        private void clearTasksToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            //remove tasks
            ClearTask();
        }
        #endregion

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
        }
 

       
        //
    }
}